/*
 *    Copyright 2011-2012 The Hook Team
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.hook.yaksha.config;

/**
 * 服务端配置类
 * 
 * @author suwuqiang 2011-12-26
 */
public class MasterConfig extends AbstractConfig {
	private static final long serialVersionUID = 1283730224175368680L;
	private static int processorCount = 1; // 当前cpu数量
	private final static String MASTER_NAME = "masterName";
	private final static String MASTER_PORT = "masterPort";
	private final static String MAX_JOBEVENT_WORKER = "maxJobEventWorker";
	private final static String MAX_MERGE_JOB_WORKER = "maxMergeJobWorker";
	private final static String MAX_CREATE_REPORT_WORKER = "maxCreateReportWorker";
	private final static String JOBS_SOURCE = "jobsSource";
	private final static String MIN_MERGE_JOB_COUNT = "minMergeJobCount";
	private final static String MAX_JOB_RESULT_BUNDLE_WAITTIME = "maxJobResultBundleWaitTime";
	private final static String EXPORT_INTERVAL = "exportInterval";
	private final static String SAVE_TMP_RESULT_TO_FILE = "saveTmpResultToFile";
	private final static String ASYN_LOAD_DISK_FILE_PRECENT = "asynLoadDiskFilePrecent";
	private final static String USE_ASYN_MODE_TO_SEND_RESPONSE = "useAsynModeToSendResponse";

	static {
		processorCount = Runtime.getRuntime().availableProcessors();
	}

	/**
	 * 是否在JobMaster中采用异步模式去发送服务端的回执消息
	 * 
	 * 比如在SocketConnector模式下就应该开启， MemConnector模式下就不用
	 * 默认打开，根据自己实现和选择的Connector判断发送是否消耗来开关
	 * 
	 * @return 是否采用异步模式发送服务端回执消息
	 */
	public boolean isUseAsynModeToSendResponse() {
		if (this.properties.containsKey(USE_ASYN_MODE_TO_SEND_RESPONSE))
			return Boolean.valueOf((String) this.properties.get(USE_ASYN_MODE_TO_SEND_RESPONSE));
		return true;
	}

	public void setUseAsynModeToSendResponse(String useAsynModeToSendResponse) {
		this.properties.put(USE_ASYN_MODE_TO_SEND_RESPONSE, useAsynModeToSendResponse);
	}

	/**
	 * Master的名称
	 * 
	 * @return Master的名称
	 */
	public String getMasterName() {
		if (this.properties.containsKey(MASTER_NAME))
			return (String) this.properties.get(MASTER_NAME);
		return null;
	}

	public void setMasterName(String masterName) {
		this.properties.put(MASTER_NAME, masterName);
	}

	/**
	 * Master开启的端口
	 * 
	 * @return Master开启的端口
	 */
	public int getMasterPort() {
		if (this.properties.containsKey(MASTER_PORT))
			return Integer.parseInt((String) this.properties.get(MASTER_PORT));
		return 7777;
	}

	public void setMasterPort(String masterPort) {
		this.properties.put(MASTER_PORT, masterPort);
	}

	/**
	 * 任务配置来源，可以自己扩展为DB，HTTP等方式，现在默认实现本地配置文件(file:xxxx)
	 * 
	 * @return 任务配置来源
	 */
	public String getJobsSource() {
		if (this.properties.containsKey(JOBS_SOURCE))
			return (String) this.properties.get(JOBS_SOURCE);
		return null;
	}

	public void setJobsSource(String jobsSource) {
		this.properties.put(JOBS_SOURCE, jobsSource);
	}

	/**
	 * JobManager处理消息事件最大线程池线程数量
	 * 
	 * @return 最大线程池线程数量
	 */
	public int getMaxJobEventWorker() {
		if (this.properties.containsKey(MAX_JOBEVENT_WORKER))
			return Integer.parseInt((String) this.properties.get(MAX_JOBEVENT_WORKER));
		return 50;
	}

	public void setMaxJobEventWorker(String maxJobEventWorker) {
		this.properties.put(MAX_JOBEVENT_WORKER, maxJobEventWorker);
	}

	/**
	 * 用于合并任务结果的线程最大设置，默认是当前处理器数 + 3
	 * 
	 * @return 合并任务结果线程数量
	 */
	public int getMaxMergeJobWorker() {
		if (this.properties.containsKey(MAX_MERGE_JOB_WORKER))
			return Integer.parseInt((String) this.properties.get(MAX_MERGE_JOB_WORKER));
		return processorCount + 3;
	}

	public void setMaxMergeJobWorker(String maxMergeJobWorker) {
		this.properties.put(MAX_MERGE_JOB_WORKER, maxMergeJobWorker);
	}

	/**
	 * 最大的用于输出统计分析结果或者载入导出临时结果的线程数，默认10
	 * 
	 * @return 输出统计分析结果或者载入导出临时结果的线程数
	 */
	public int getMaxCreateReportWorker() {
		if (this.properties.containsKey(MAX_CREATE_REPORT_WORKER))
			return Integer.parseInt((String) this.properties.get(MAX_CREATE_REPORT_WORKER));
		return 10;
	}

	public void setMaxCreateReportWorker(String maxCreateReportWorker) {
		this.properties.put(MAX_CREATE_REPORT_WORKER, maxCreateReportWorker);
	}

	/**
	 * 合并最小的结果数，默认为1,如果不达到这个值，等待MAX_JOB_RESULT_BUNDLE_WAITTIME到获得必要个数为止
	 * 
	 * @return 合并最小的结果数
	 */
	public int getMinMergeJobCount() {
		if (this.properties.containsKey(MIN_MERGE_JOB_COUNT))
			return Integer.parseInt((String) this.properties.get(MIN_MERGE_JOB_COUNT));
		return 1;
	}

	public void setMinMergeJobCount(String minMergeJobCount) {
		this.properties.put(MIN_MERGE_JOB_COUNT, minMergeJobCount);
	}

	/**
	 * MinMergeJobCount,单位毫秒，最大等待组成一个bundle批量处理的时间，默认为60秒
	 * 
	 * @return MinMergeJobCount
	 */
	public long getMaxJobResultBundleWaitTime() {
		if (this.properties.containsKey(MAX_JOB_RESULT_BUNDLE_WAITTIME))
			return Long.parseLong((String) this.properties.get(MAX_JOB_RESULT_BUNDLE_WAITTIME)) * 1000;
		return 60 * 1000;
	}

	public void setMaxJobResultBundleWaitTime(String maxJobResultBundleWaitTime) {
		this.properties.put(MAX_JOB_RESULT_BUNDLE_WAITTIME, maxJobResultBundleWaitTime);
	}

	/**
	 * 输出临时文件间隔(单位秒，默认10分钟),如果设置了saveTmpResultToFile，该时间设置无效，每次都会有导出临时文件
	 * 
	 * @return 输出临时文件间隔
	 */
	public long getExportInterval() {
		if (this.properties.containsKey(EXPORT_INTERVAL))
			return Long.parseLong((String) this.properties.get(EXPORT_INTERVAL)) * 1000;
		return 600 * 1000;
	}

	public void setExportInterval(String exportInterval) {
		this.properties.put(EXPORT_INTERVAL, exportInterval);
	}

	/**
	 * 数据量较小的情况下请勿使用
	 * 
	 * 导出后清除对应的map内的数据，下次合并过程中再尝试从磁盘载入，通过配置开关判断是否实施
	 * 
	 * @return
	 */
	public boolean getSaveTmpResultToFile() {
		if (this.properties.containsKey(SAVE_TMP_RESULT_TO_FILE))
			return Boolean.parseBoolean((String) this.properties.get(SAVE_TMP_RESULT_TO_FILE));
		return true;
	}

	public void setSaveTmpResultToFile(String saveTmpResultToFile) {
		this.properties.put(SAVE_TMP_RESULT_TO_FILE, saveTmpResultToFile);
	}

	/**
	 * 配合磁盘换内存的方式，判断什么时候可以异步载入文件
	 * 
	 * @return
	 */
	public int getAsynLoadDiskFilePrecent() {
		if (this.properties.containsKey(ASYN_LOAD_DISK_FILE_PRECENT))
			return Integer.parseInt((String) this.properties.get(ASYN_LOAD_DISK_FILE_PRECENT));
		return 85;
	}

	public void setAsynLoadDiskFilePrecent(String asynLoadDiskFilePrecent) {
		this.properties.put(ASYN_LOAD_DISK_FILE_PRECENT, asynLoadDiskFilePrecent);
	}
}
